"""
Fortran COMMON block and legacy construct analyzer.

This module provides analysis of legacy Fortran constructs including:
- COMMON blocks and global data sharing
- EQUIVALENCE statements and variable aliasing
- Legacy control flow (computed GOTO, etc.)
- Statement functions
"""

import logging
from typing import Dict, List, Any, Set, Optional, Tuple
from collections import defaultdict

from ...core.error_handler import AnalysisError, log_info


class CommonBlock:
    """Information about a COMMON block."""
    
    def __init__(self, name: str = "blank"):
        self.name = name  # "blank" for unnamed COMMON
        self.variables = []  # List of variable info
        self.locations = []  # List of (file, line) where defined
        self.total_size = 0  # Size in storage units
        
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        return {
            'name': self.name,
            'variables': self.variables,
            'locations': self.locations,
            'total_size': self.total_size,
            'is_blank_common': self.name == "blank"
        }


class EquivalenceGroup:
    """Information about an EQUIVALENCE group."""
    
    def __init__(self):
        self.variables = []  # List of equivalent variables
        self.locations = []  # List of (file, line) where defined
        self.conflicts = []  # Potential conflicts with other groups
        
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        return {
            'variables': self.variables,
            'locations': self.locations,
            'conflicts': self.conflicts
        }


class LegacyAnalyzer:
    """
    Analyzer for legacy Fortran constructs.
    
    Handles analysis of older Fortran features that are still encountered
    in legacy code but generally discouraged in modern Fortran.
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.common_blocks = {}  # name -> CommonBlock
        self.equivalence_groups = []  # List of EquivalenceGroup
        self.computed_gotos = []  # List of computed GOTO statements
        self.statement_functions = {}  # name -> statement function info
        
    def analyze_legacy_constructs(self, parsed_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Analyze legacy constructs in parsed Fortran data.
        
        Args:
            parsed_data: Parsed Fortran file data
            
        Returns:
            Legacy construct analysis results
        """
        try:
            filename = parsed_data.get('filename', 'unknown')
            log_info(f"Analyzing legacy constructs in {filename}")
            
            # Analyze COMMON blocks
            self._analyze_common_blocks(parsed_data)
            
            # Analyze EQUIVALENCE statements
            self._analyze_equivalence(parsed_data)
            
            # Analyze computed GOTOs
            self._analyze_computed_gotos(parsed_data)
            
            # Analyze statement functions
            self._analyze_statement_functions(parsed_data)
            
            result = {
                'filename': filename,
                'common_blocks': {name: cb.to_dict() for name, cb in self.common_blocks.items()},
                'equivalence_groups': [eq.to_dict() for eq in self.equivalence_groups],
                'computed_gotos': self.computed_gotos,
                'statement_functions': self.statement_functions,
                'legacy_warnings': self._generate_warnings(),
                'modernization_suggestions': self._suggest_modernization(),
                'statistics': self._compute_statistics()
            }
            
            log_info(f"Legacy analysis complete for {filename}: "
                    f"{len(self.common_blocks)} COMMON blocks, "
                    f"{len(self.equivalence_groups)} EQUIVALENCE groups")
            
            return result
            
        except Exception as e:
            self.logger.error(f"Error analyzing legacy constructs: {e}")
            raise AnalysisError(f"Legacy construct analysis failed: {e}")
    
    def _analyze_common_blocks(self, parsed_data: Dict[str, Any]):
        """Analyze COMMON blocks."""
        for common_data in parsed_data.get('common_blocks', []):
            name = common_data.get('name', 'blank')
            
            if name not in self.common_blocks:
                self.common_blocks[name] = CommonBlock(name)
            
            common_block = self.common_blocks[name]
            common_block.locations.append((
                parsed_data.get('filename', 'unknown'),
                common_data.get('line_number', 0)
            ))
            
            # Add variables (would need more sophisticated parsing)
            for var in common_data.get('variables', []):
                if var not in [v['name'] for v in common_block.variables]:
                    common_block.variables.append({
                        'name': var,
                        'type': 'unknown',  # Would need type analysis
                        'size': 1  # Default size
                    })
    
    def _analyze_equivalence(self, parsed_data: Dict[str, Any]):
        """Analyze EQUIVALENCE statements."""
        # This would need more sophisticated parsing to extract
        # EQUIVALENCE statements from source code
        pass
    
    def _analyze_computed_gotos(self, parsed_data: Dict[str, Any]):
        """Analyze computed GOTO statements."""
        # Simple pattern matching for computed GOTOs
        source_lines = parsed_data.get('source_lines', [])
        for i, line in enumerate(source_lines):
            line_upper = line.strip().upper()
            if 'GOTO' in line_upper and '(' in line_upper:
                # Potential computed GOTO
                self.computed_gotos.append({
                    'line_number': i + 1,
                    'statement': line.strip(),
                    'type': 'computed_goto'
                })
    
    def _analyze_statement_functions(self, parsed_data: Dict[str, Any]):
        """Analyze statement functions."""
        # Statement functions would need sophisticated parsing
        # as they look like assignments but are actually function definitions
        pass
    
    def _generate_warnings(self) -> List[Dict[str, Any]]:
        """Generate warnings about legacy construct usage."""
        warnings = []
        
        # Warn about COMMON blocks
        if self.common_blocks:
            warnings.append({
                'type': 'common_block_usage',
                'severity': 'warning',
                'message': f"Found {len(self.common_blocks)} COMMON block(s). "
                          "Consider using modules for data sharing.",
                'count': len(self.common_blocks)
            })
        
        # Warn about computed GOTOs
        if self.computed_gotos:
            warnings.append({
                'type': 'computed_goto_usage',
                'severity': 'warning',
                'message': f"Found {len(self.computed_gotos)} computed GOTO(s). "
                          "Consider using SELECT CASE or IF-THEN-ELSE.",
                'count': len(self.computed_gotos)
            })
        
        return warnings
    
    def _suggest_modernization(self) -> List[Dict[str, Any]]:
        """Suggest modernization approaches for legacy code."""
        suggestions = []
        
        if self.common_blocks:
            suggestions.append({
                'construct': 'COMMON blocks',
                'modern_alternative': 'Modules with public variables or derived types',
                'benefits': ['Better encapsulation', 'Type safety', 'Explicit interfaces'],
                'example': 'module shared_data\n  real :: temperature\nend module'
            })
        
        if self.computed_gotos:
            suggestions.append({
                'construct': 'Computed GOTO',
                'modern_alternative': 'SELECT CASE construct',
                'benefits': ['Better readability', 'Structured control flow', 'Easier maintenance'],
                'example': 'select case (choice)\ncase (1)\n  ! code\ncase (2)\n  ! code\nend select'
            })
        
        return suggestions
    
    def _compute_statistics(self) -> Dict[str, Any]:
        """Compute legacy construct statistics."""
        return {
            'total_common_blocks': len(self.common_blocks),
            'named_common_blocks': len([cb for cb in self.common_blocks.values() if cb.name != 'blank']),
            'blank_common_blocks': 1 if 'blank' in self.common_blocks else 0,
            'total_equivalence_groups': len(self.equivalence_groups),
            'computed_gotos': len(self.computed_gotos),
            'statement_functions': len(self.statement_functions),
            'legacy_constructs_found': (
                len(self.common_blocks) + len(self.equivalence_groups) +
                len(self.computed_gotos) + len(self.statement_functions)
            )
        }
    
    def get_common_block_conflicts(self) -> Dict[str, List[str]]:
        """
        Detect potential conflicts in COMMON block usage.
        
        Returns:
            Dictionary mapping COMMON block names to list of conflicts
        """
        conflicts = {}
        
        for name, common_block in self.common_blocks.items():
            block_conflicts = []
            
            # Check for multiple definitions with different variable lists
            if len(common_block.locations) > 1:
                block_conflicts.append(f"Defined in {len(common_block.locations)} locations")
            
            # Check for blank COMMON usage (generally discouraged)
            if name == 'blank':
                block_conflicts.append("Uses blank COMMON (discouraged)")
            
            if block_conflicts:
                conflicts[name] = block_conflicts
        
        return conflicts